package yhao.demo.autocode.core.feignmapper;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class FeignToDocxHelper {
    //扫描包路径
    private String packageRoot;

    public final static String CONF_DIR_PATH =
            System.getProperty("user.home") + File.separator + "yhao.feignTodocx";

    /**
     * @param packageRoot 扫描包路径
     */
    public FeignToDocxHelper(String packageRoot) {
        this.packageRoot = packageRoot;
    }

    public void doMapper() throws Exception {
        List<FeignDefinition> feignDefinitions = ClassPathScanner.getInstance().doScan(packageRoot);
        //模板接口文档
        XWPFTable apiTemplateTable = getApiTemplateTable();
        //模板模型文档
        XWPFTable modelTemplateTable = getModelTemplateTable();

        Resource resource = new ClassPathResource("feignToDocx/template.docx");
        //读取文档内容
        XWPFDocument document = new XWPFDocument(resource.getInputStream());
        setStyle(document);
        for (FeignDefinition fegin : feignDefinitions) {
            XWPFParagraph paragraph = document.createParagraph();
            paragraph.setStyle("1");
            XWPFRun run=paragraph.createRun();
            run.setText(fegin.getClassName());
            for (FeignDefinition.FeignMethodDefinition methodDef : fegin.getMethodDefinitions()) {
                XWPFParagraph paragraphFeign = document.createParagraph();
                paragraphFeign.setStyle("2");
                XWPFRun runFeign=paragraphFeign.createRun();
                runFeign.setText(methodDef.getMethodName());
                XWPFTable feginMethod = copyTable(apiTemplateTable, document.createTable());
                feginMethod.getRows().get(0).getCell(1).setText(fegin.getClassName() + "." + methodDef.getMethodName());
                feginMethod.getRows().get(1).getCell(1).setText(methodDef.getDesc());
                feginMethod.getRows().get(2).getCell(1).setText(methodDef.getParameterType());
                feginMethod.getRows().get(3).getCell(1).setText(
                        methodDef.getGenericType() + "<" + methodDef.getReturnType() + ">");
                feginMethod.getRows().get(4).getCell(1).setText(methodDef.getReturnTypeDesc());

                document.createParagraph();

                XWPFTable parameterType = copyTable(modelTemplateTable, document.createTable());
                parameterType.getRows().get(0).getCell(1).setText(methodDef.getParameterType());
                parameterType.getRows().get(1).getCell(1).setText(methodDef.getParameterTypeDesc());
                addPropertyInfo(parameterType,methodDef.getParameterMap());
                document.createParagraph();

                XWPFTable returnType = copyTable(modelTemplateTable, document.createTable());
                returnType.getRows().get(0).getCell(1).setText(methodDef.getReturnType());
                returnType.getRows().get(1).getCell(1).setText(methodDef.getReturnTypeDesc());
                addPropertyInfo(returnType,methodDef.getReturnMap());
            }
            document.createParagraph();
        }
        makeFile(document);
        System.out.println("文档生成...DONE");
        System.out.println();
        System.out.println("完成操作...");
        System.out.println("请到以下地址复制文件..." + CONF_DIR_PATH);
    }

    private void setStyle(XWPFDocument document) {
        try {
            Resource resource = new ClassPathResource("feignToDocx/style.docx");
            XWPFDocument style = new XWPFDocument(resource.getInputStream());
            // 获得模板文档的整体样式
            CTStyles wordStyles = style.getStyle();
            XWPFStyles newStyles = document.createStyles();
            newStyles.setStyles(wordStyles);
        } catch (Exception e) {}
    }

    private void addPropertyInfo(XWPFTable table, LinkedHashMap<String, String> propertyMap) {
        boolean flag = false;
        XWPFTableRow styleRow = table.getRow(table.getRows().size()-1);
        for(Map.Entry<String,String> entry:propertyMap.entrySet()){
            XWPFTableRow targetRow;
            if(flag){
                targetRow = table.createRow();
                targetRow.getCtRow().setTrPr(styleRow.getCtRow().getTrPr());
            }else{
                targetRow = styleRow;
                flag = true;
            }
            targetRow.getCell(0).setText(entry.getKey());
            targetRow.getCell(0).getCTTc().setTcPr(styleRow.getCell(0).getCTTc().getTcPr());
            targetRow.getCell(1).setText(entry.getValue());
            targetRow.getCell(1).getCTTc().setTcPr(styleRow.getCell(1).getCTTc().getTcPr());
        }
    }

    private XWPFTable copyTable(XWPFTable source, XWPFTable target) {
        target.removeRow(0);
        for (XWPFTableRow sourceRow : source.getRows()) {
            XWPFTableRow targetRow = new XWPFTableRow(target.getCTTbl().addNewTr(), target);
            target.getRows().add(targetRow);
            List<XWPFTableCell> cellList = sourceRow.getTableCells();
            targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr());
            //复制列及其属性和内容
            for (int i=0;i< cellList.size();i++) {
                XWPFTableCell sourceCell = cellList.get(i);
                XWPFTableCell targetCell = targetRow.createCell();
                //列属性
                targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());

                targetCell.setText(sourceCell.getText());
            }
        }
        return target;
    }

    private XWPFTable getApiTemplateTable() throws IOException {
        Resource resource = new ClassPathResource("feignToDocx/apiTemplate.docx");
        XWPFDocument document = new XWPFDocument(resource.getInputStream());
        return document.getTables().get(0);
    }

    private XWPFTable getModelTemplateTable() throws IOException {
        Resource resource = new ClassPathResource("feignToDocx/modelTemplate.docx");
        XWPFDocument document = new XWPFDocument(resource.getInputStream());
        return document.getTables().get(0);
    }

    private void makeFile(XWPFDocument document) throws IOException {
        File root = new File(CONF_DIR_PATH);
        if (!root.exists()) {
            root.mkdir();
        }
        File file = new File(CONF_DIR_PATH + File.separator + "文档描述.docx");
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        document.write(new FileOutputStream(file));
    }

    @Override
    public String toString() {
        return "FeignToDocxHelper{" +
                "packageRoot='" + packageRoot + '\'' +
                '}';
    }
}
